package com.xianggu.spring.spi;

import org.springframework.core.io.DefaultResourceLoader;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * 解析 META-INF/spring.factories 文件的工具类
 */
public class SpringFactoriesLoader {

    // 定义 spring.factories 文件的路径
    private static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

    /**
     * 加载 spring.factories 文件并解析为 Map
     *
     * @param classLoader 类加载器
     * @return 键值对形式的 Map，键是接口或抽象类，值是实现类的列表
     */
    public static Map<String, List<String>> loadFactories(ClassLoader classLoader) {
        Map<String, List<String>> result = new HashMap<>();
        try {
            // 获取所有 META-INF/spring.factories 文件的 URL
            Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                System.out.println("url:" + url);
                // 读取文件内容并解析
                Properties properties = loadProperties(url);
                for (Map.Entry<?, ?> entry : properties.entrySet()) {
                    String factoryTypeName = ((String) entry.getKey()).trim();
                    String[] factoryImplementationNames =
                            ((String) entry.getValue()).trim().split(",");
                    // 将实现类名称添加到结果中
                    result.computeIfAbsent(factoryTypeName, k -> new ArrayList<>())
                            .addAll(Arrays.asList(factoryImplementationNames));
                }
            }
        } catch (IOException e) {
            throw new IllegalArgumentException("Failed to load factories from location [" +
                    FACTORIES_RESOURCE_LOCATION + "]", e);
        }
        return result;
    }

    /**
     * 从 URL 读取 properties 文件
     *
     * @param url 文件 URL
     * @return Properties 对象
     */
    private static Properties loadProperties(URL url) throws IOException {
        Properties properties = new Properties();
        try (InputStream inputStream = url.openStream();
             BufferedReader reader = new BufferedReader(
                     new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
            properties.load(reader);
        }
        return properties;
    }

    /**
     * 测试方法
     */
    public static void main(String[] args) {
        ClassLoader classLoader = new DefaultResourceLoader().getClassLoader();
//        ClassLoader classLoader = SpringFactoriesLoader.class.getClassLoader();
        Map<String, List<String>> factories = loadFactories(classLoader);

        // 打印解析结果
        for (Map.Entry<String, List<String>> entry : factories.entrySet()) {
            System.out.println("Type: " + entry.getKey());
            System.out.println("Implementations: " + entry.getValue());
        }
    }
}